﻿using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using System;
using System.Text;
using System.Threading.Tasks;

namespace MqttCore
{
    public class MqttEasyClient
    {
        private IMqttClient _mqttClient;

        public IMqttClient MqttClient { get; private set; }

        #region 配置

        public string ServerHost { get; private set; }

        public int Port { get; private set; }

        public string Username { get; private set; }

        public string Password { get; private set; }

        #endregion

        public MqttEasyClient(string server, int port = 1883)
        {
            ServerHost = server;
            Port = port;
        }

        public MqttEasyClient(string server, string uid,string pwd,int port = 1883)
        {
            Username = uid;
            Password = pwd;
            ServerHost = server;
            Port = port;
        }

        public async Task ConnectMqttServerAsync()
        {
            try
            {
                var factory = new MqttFactory();

                _mqttClient ??= factory.CreateMqttClient();

                var options = new MqttClientOptionsBuilder()
                    .WithTcpServer(ServerHost, Port)
                    .WithCredentials(Username, Password)
                    .WithClientId(Guid.NewGuid().ToString().Substring(0, 5))
                    .Build();

                //消息
                _mqttClient.UseApplicationMessageReceivedHandler(e =>
                {
                    StringBuilder str = new StringBuilder();
                    str.AppendLine("### 收到的信息 ###");
                    str.AppendLine($"+ Topic = {e.ApplicationMessage.Topic}");//主题
                    str.AppendLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");//页面信息
                    str.AppendLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");//消息等级
                    str.AppendLine($"+ Retain = {e.ApplicationMessage.Retain}");//是否保留
                    Console.WriteLine(str);
                });

                //重连机制
                _mqttClient.UseDisconnectedHandler(async e =>
                {
                    Console.WriteLine("与服务器断开连接！");
                    await Task.Delay(TimeSpan.FromSeconds(5));
                    try
                    {
                        await _mqttClient.ConnectAsync(options);
                    }
                    catch (Exception exp)
                    {
                        Console.Write($"重新连接服务器失败 Msg：{exp}");
                    }
                });

                _mqttClient.UseConnectedHandler(async e =>
                {
                    Console.WriteLine("与服务器连接成功！");
                    await Task.Delay(TimeSpan.FromMilliseconds(200));
                    await Subscribe("Test");
                });

                await _mqttClient.ConnectAsync(options);

                Console.Write("连接服务器成功！输入任意内容并回车进入菜单页面！");
            }
            catch (Exception exp)
            {
                Console.Write($"连接服务器失败 Msg：{exp}");
            }
        }

        /// <summary>
        /// 订阅
        /// </summary>
        /// <param name="topicName"></param>
        public async Task Subscribe(string topicName)
        {
            string topic = topicName.Trim();
            if (string.IsNullOrEmpty(topic))
            {
                Console.Write("订阅主题不能为空！");
                return;
            }

            if (!_mqttClient.IsConnected)
            {
                Console.Write("MQTT客户端尚未连接！");
                return;
            }
            await _mqttClient.SubscribeAsync(topic);
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="topicName"></param>
        public async Task Unsubscribe(string topicName)
        {
            string topic = topicName.Trim();
            if (string.IsNullOrEmpty(topic))
            {
                Console.Write("订阅主题不能为空！");
                return;
            }

            if (!_mqttClient.IsConnected)
            {
                Console.Write("MQTT客户端尚未连接！");
                return;
            }
            await _mqttClient.UnsubscribeAsync(topic);
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="message"></param>
        public async Task Publish(string topicName, string message)
        {
            string topic = topicName.Trim();
            string msg = message.Trim();

            if (string.IsNullOrEmpty(topic))
            {
                Console.Write("主题不能为空！");
                return;
            }
            if (!_mqttClient.IsConnected)
            {
                Console.Write("MQTT客户端尚未连接！");
                return;
            }

            var MessageBuilder = new MqttApplicationMessageBuilder()
                .WithTopic(topic)
                .WithPayload(msg)
                .WithExactlyOnceQoS()
                .WithRetainFlag()
                .Build();

            await _mqttClient.PublishAsync(MessageBuilder);
        }
    }
}